今天我們來說明如何將gt表格呈現於Django app中,內容參考自官方Solar Zenith Angles範例。
建立一個名為core的django project。
django-admin startproject core .
建立一個名為gt的django app(以下簡稱為gt app)。
python manage.py startapp gt
將gt app加入位於core/settings.py內的INSTALLED_APPS中。
# core/settings.py
INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "gt",
]
於gt app中建立urls.py,並設定urlpatterns。
# gt/urls.py
from django.urls import path
from . import views
urlpatterns = [
    path("", views.index, name="index"),
]
修改core/urls.py,加入gt app的urlpatterns。
# core/urls.py
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
    path("admin/", admin.site.urls),
    path("", include("gt.urls")),
]
index()函數 # gt/views.py
 from functools import cache
 import polars as pl
 from django.shortcuts import render
 from great_tables import GT, html
 from great_tables.data import sza
 @cache
 def get_sza():
     return pl.from_pandas(sza)
 def index(request):
     sza_pivot = (
         get_sza()
         .filter((pl.col("latitude") == "20") & (pl.col("tst") <= "1200"))
         .select(pl.col("*").exclude("latitude"))
         .drop_nulls()
         .pivot(values="sza", index="month", on="tst", sort_columns=True)
     )
     sza_gt = (
         GT(sza_pivot, rowname_col="month")
         .data_color(
             domain=[90, 0],
             palette=["rebeccapurple", "white", "orange"],
             na_color="white",
         )
         .tab_header(
             title="Solar Zenith Angles from 05:30 to 12:00",
             subtitle=html("Average monthly values at latitude of 20°N."),
         )
         .sub_missing(missing_text="")
     )
     context = {"sza_gt": sza_gt.as_raw_html()}
     return render(request, "gt/index.html", context)
分段說明如下:
get_sza()會返回一個Polars DataFrame,是由gt提供的sza Pandas DataFrame轉換而來。由於DataFrame於此app中不會變動,所以可以將@cache(註1)裝飾在get_sza()上。index()為使用者以HTTP GET訪問「"/"」時使用的函數。sza_pivot為Polars DataFrame的整理過程;sza_gt則為表格的製作過程。context = {"sza_gt": sza_gt.as_raw_html()}為整合的關鍵。我們使用GT.as_raw_html()來生成HTML,並置於context中。index.html。其中,context可以視為製作index.html所需要的額外資訊。於gt app中建立一個templates資料夾,並於templates資料夾中再建立一個gt資料夾。最後於此資料夾中(即gt/templates/gt)建立index.html。
 <!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Django-GT Website</title>
  </head>
  <body>
    <main>
        <h1 style="text-align:center">Great Tables shown in Django</h1>  
    </main>
    <div>
        {{ sza_gt | safe}}
    </div>
  </body>
</html>
於index.html中,我們可以使用Django template語法{{ sza_gt }}來取得於context所傳入的值。但請注意這邊必須使用| safe這個filter來確認此HTML是安全的,如此才可於瀏覽器中順利呈現gt表格。
由於gt app並沒有使用到資料庫,所以此命令為選擇性執行。如果沒有執行,gt表格也可正確呈現,只是命令列會有尚未migration的警告訊息。
python manage.py migrate
於命令列中執行下列指令:
python manage.py runserver
接著打開瀏覽器前往預設網址,如http://127.0.0.1:8000/,就可以見到下面這個漂亮的表格:
如果不喜歡於template中加入| safe的話,可以改為在view function中添加。舉例來說,可以寫一個mark_gt_safe()來幫忙在index()中呼叫GT.as_raw_html():
# gt/views.py
...
from django.utils.safestring import mark_safe
def mark_gt_safe(gt):
 if isinstance(gt, GT):
     return mark_safe(gt.as_raw_html())
 return gt
def index(request):
    ...
    context = {"sza_gt": mark_gt_safe(sza_gt)}
    return render(request, "gt/index.html", context)
這麼一來在index.html中,就可以直接使用{{ sza_gt }}來取得gt表格的HTML格式,而不必使用{{ sza_gt | safe}}了。
如果對裝飾器這個概念仍然不是那麼清楚的朋友,可以參考我於2023年鐵人賽的系列文 ── Python十翼:與未來的自己對話,其中有詳細的說明。
本日所有程式碼可參考gt-django repo。